'''
    exercise one: 列表
'''
from setuptools.command.build_ext import if_dl

arr = []
# 顺序添加
arr.append(21)
print(arr)
# 在arr末尾添加元素
arr.extend([12])
print(arr)
# insert
arr.insert(1, [45])
print(arr)
arr.append(12)
print(arr)
# 移除一个
arr.remove(12)
print(arr)

print(arr.pop())
print(arr)

# arr.clear()
# print(arr) # == del a[:]
# 找到第一个元素的index[从左到右]
print(arr.index([45]))
arr.count(21)
new_arr = [4, 8, 5, 3, 7]
new_arr.sort()
print(new_arr)

# 浅拷贝
print(new_arr.copy())

'''
    exercise two:列表作为栈使用
'''
stack = [3, 4, 5]
# 入栈
stack.append(6)
stack.append(7)
# 出栈
print(stack.pop())

'''
    列表作为队列使用
    列表用作队列的话，先进先出。但是列表作为队列是比较低效的，因为所有的其他元素都必须移动一位
    可以使用 from collections import deque
'''
from collections import deque

queue = deque(['Chinese', "English", "Math"])
queue.append("Art")
print(queue)
# 出队
print(queue.popleft())
print("\n-------------------------------------------------------\n")

'''
    列表推导式
'''
squares = [i * i for i in range(10)]
print(squares)
squares = list(map(lambda i: i ** 2, range(10)))
print(squares)

turtle_combiner = [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
print(turtle_combiner)
# 等价于
# combs = []
# for x in [1,2,3]:
#      for y in [3,1,4]:
#          if x != y:
#              combs.append((x, y))

from math import pi

pi_round = [str(round(pi, i)) for i in range(1, 6)]
print(pi_round)

print("\n-------------------------------------------------------\n")

"""
exercise three: del语句
"""
prin_arr = [-2, 4, 56, 74, 235]
# 删掉prin_arr第0索引的值
del prin_arr[0]
del prin_arr[2:4]  # 超出bound_index将后面的都删掉
print(prin_arr)
# del也可以删掉整个变量
# 此后再引用 a 时会报错（直到另一个值被赋给它）。我们会在后面了解到 del 的其他用法
print("\n-------------------------------------------------------\n")

"""
    另一种序列类型
    元组是不可变的
    immutable: 不可变的
    but they can contain mutable objects:但是他们可以包含可变对象
"""

t = 1234, 5321, 'hello!'
print(t[0])
print(t)
v = ([1, 2, 3], [3, 2, 1])
print(v)
v[0].append(77)
print(v)
# 元组打包，逆过来也是可以的
tt = 1, 2, 3
# 序列解包
x, y, z = tt
# 多重赋值其实也只是元组打包和序列解包的组合
print("\n-------------------------------------------------------\n")
'''
    exercise five: 集合 
    Python也有集合类型，集合是由不重复元素组成的无序的集，它的基本语法包括成员检测和消除重复元素。
    支持操作：联合、交集、差集、等等
'''

print("\n-------------------------------------------------------\n")
# 创建集合set() / {}
# 但是空集合只能用set(),因为{}是空字典
basket = {'apple', 'orange', 'pear', 'banana'}
print(basket)
print('orange' in basket)

a = set('abracadabra')
b = set('alacazam')
print(a)
print(b)
print(a - b)    # letters in a but not in b
print(a | b)    # letters in a or b or both
print(a & b)    # letters in both a and b
print(a ^ b)    # letters in a or b but not both
print("\n-------------------------------------------------------\n")
# 集合也支持列表推导式
a = {x for x in 'abracadabra' if x not in 'abc'}
print(a)  # {'r','d'}

'''
    exercise six: 字典 dict
    关键字可以是任意不可变类型，通常是字符串或数字。如果元组包含了可变对象，那么久不可以做key。
    列表不能用作key，因为列表通过索引、切片或append、extend之类的方法来改变【append作为一个整体添加，extend 将可遍历的每个元素逐一添加到末尾】
'''
tel = {'jack':4088,'sape':4139}
tel['guido'] = 4127
print(tel)
print(tel['jack'])
del tel[('sape')]
print(sorted(tel))
print('guido is in tel ?','guido' in tel)
# dict() 构造器可以直接从键值对序列中创建字典
dict_rr = dict([('sape',4139),('guido',4127),('jack', 4098)])
# 关键字参数指定键值对更方便
print(dict(spce=4329, guido=3204, jack=3042))
print(dict_rr)
# 推导式创建字典
x = { x: a for a in range(0, len('abc')) for x  in set('abc')}
print(x)


# 字典的遍历
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k,v in knights.items():
    print(k, "=", v)

# 序列遍历区别使用enumerate
for i,v in enumerate(['tic', 'tac', 'toe']):
    print(i,v)

# 当同时在两个或更多序列中循环时，可以使用zip()函数将其元素一一匹配
a=[1,2,3,4]
b=['a','b','c','d']
for i,v in zip(a,b):
    print(f"{i}={v}")


# 当逆向循环一个序列时，先正向定位序列，然后调用reversed()函数
for i in reversed(range(1,10,2)):
    print(i) # reversed(1,3,5,7,9)
print("\n-------------------------------------------------------\n")

# sorted()返回一个排好序的新序列
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
    print(f, end=' ')

print("\n-------------------------------------------------------\n")
import math
raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5,float('NaN'), 47.8]
filtered_data = []
for value in raw_data:
    if not math.isnan(value):
        filtered_data.append(value)

print(filtered_data)
print("\n-------------------------------------------------------\n")

'''
    exercise seven: 深入条件控制
    比较操作符 in 和 not in 校验一个值是否在不在一个序列里。
    操作符 is 和 is not 比较两个对象是不是同一个对象，优先级低于数值运算符低。
    比较操作可以传递：例如 a<b==c,会校验是否a小于b并且b等于c。
    比较操作可以通过布尔运算符and 和 or 来组合，并且比较操作(或其他任何布尔运算)的结果都可以用not来取反。
    not优先级最高，or优先级最低，因此 A and not B or C 等价于 A and (not B) or C. 
    布尔运算符 and 和 or 也被称为短路运算符：它们的参数从左到右解析，一旦可以确定结果解析就会停止。例如
    如果A和C为真二B为假，那么A and B and C不会解析C。
'''
string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
not_null = string1 or string2 or string3
print(not_null) # Trondheim

# 序列和其他类型的比较
'''
    (1,2,3) < (1,2,4)
    [1,2,3] < [1,2,4]
    'ABC' < 'C' < 'Pascal' < 'Python'
    (1,2,3,4) < (1,2,4)
    (1,2) < (1,2,-1)
    (1,2,3) == (1.0,2.0,3.0)
     (1,2,('aa','ab')) < (1,2,('abc','a'),4)
'''